/**
 * Copyright (c) [2025] [AGIROS] 
 * [travoddsgen] is licensed under Mulan PSL v2. 
 * You can use this software according to the terms and conditions of the Mulan PSL v2. 
 * You may obtain a copy of Mulan PSL v2 at: 
 *          http://license.coscl.org.cn/MulanPSL2 
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 
 * See the Mulan PSL v2 for more details.
 */ 

#include "CppLangTypeSupportSourceVisitor.h"
#include "CppLangTypeNameVisitor.h"
#include <fstream>

CppLangTypeSupportSourceVisitor::CppLangTypeSupportSourceVisitor(
    const std::string& outputDir, 
    const std::string& fileName, 
    CppLangTypeNameVisitor* typeNameVisitor,
    const std::string& headerFile)
    : FileGenVisitor(outputDir, fileName),
      typeNameVisitor_(typeNameVisitor),
      headerFile_(headerFile) {
    serializeVisitor_ = new CppLangSerializeVisitor(typeNameVisitor_);
    deserializeVisitor_ = new CppLangDeserializeVisitor(typeNameVisitor_);
    serializeKeyVisitor_ = new CppLangSerializeKeyVisitor(typeNameVisitor_);
    getSerializeSizeVisitor_ = new CppLangGetSerializeSizeVisitor(typeNameVisitor_);
    getMaxSerializeSizeVisitor_ = new CppLangGetMaxSerializeSizeVisitor(typeNameVisitor_);
}

void CppLangTypeSupportSourceVisitor::visit(SpecificationNode& node) {
    std::string headerFile = headerFile_;
    // 文件头的宏声明
    std::string headers = "#include \"" + headerFile + "\"\n";
    content_ += headers + "\n";

    // AGIDDS命名空间
    content_ += "USING_AGIDDS_NAMESPACE\n\n";

    // __cplusplus宏定义开始
    content_ += "#ifdef __cplusplus\n";
    content_ += "extern \"C\" {\n";
    content_ += "#endif\n\n";

    // 递归访问子节点
    if (node.definitions_) {
        node.definitions_->accept(*this);
    }

    // __cplusplus宏定义结尾
    content_ += "#ifdef __cplusplus\n";
    content_ += "}\n";
    content_ += "#endif\n";

    // 将_content写入文件
    writeToFile();
}

void CppLangTypeSupportSourceVisitor::visit(IncludeDclNode& node) {
    // 递归访问子节点
    std::string includedFile = typeNameVisitor_->getIncludedFileName(node);
    content_ += "#include \"" + includedFile + "TypeSupport.h\"\n";
    content_ += "\n";
}

void CppLangTypeSupportSourceVisitor::visit(StructDefNode& node) {
    std::string structName = typeNameVisitor_->findName(&node);
    // 生成get_instance单例函数的实现
    generateGetInstanceFuncImpl(node);
    // 生成create_data函数的实现
    generateCreateDataFuncImpl(node);
    // 生成delete_data函数的实现
    generateDeleteDataFuncImpl(node);
    // 生成copy_data函数的实现
    generateCopyDataFuncImpl(node);
    // 生成get_serialized_data_size函数的实现
    generateGetSerializedDataSizeFuncImpl(node);
    // 生成get_max_serialized_data_size函数的实现
    generateGetMaxSerializedDataSizeFuncImpl(node);
    // 生成serialize_data函数的实现
    generateSerializeDataFuncImpl(node);
    // 生成deserialize_data函数的实现
    generateDeserializeDataFuncImpl(node);
    // 生成get_typeobject函数的实现
    generateGetTypeObjectFuncImpl(node);
    // 生成MakeKey函数的实现
    generateMakeKeyFuncImpl(node);
    // 生成get_instancehandle函数的实现
    generateGetInstanceHandleFuncImpl(node);
    // 生成has_key函数的实现
    generateHasKeyFuncImpl(node);
    // 生成get_typename函数的实现
    generateGetTypenameFuncImpl(node);
}

void CppLangTypeSupportSourceVisitor::visit(UnionDefNode& node) {
    std::string structName = typeNameVisitor_->findName(&node);
    // 生成get_instance单例函数的实现
    generateGetInstanceFuncImpl(node);
    // 生成create_data函数的实现
    generateCreateDataFuncImpl(node);
    // 生成delete_data函数的实现
    generateDeleteDataFuncImpl(node);
    // 生成copy_data函数的实现
    generateCopyDataFuncImpl(node);
    // 生成get_serialized_data_size函数的实现
    // generateGetSerializedDataSizeFuncImpl(node);
    // 生成get_max_serialized_data_size函数的实现
    // generateGetMaxSerializedDataSizeFuncImpl(node);
    // 生成serialize_data函数的实现
    generateSerializeDataFuncImpl(node);
    // 生成deserialize_data函数的实现
    generateDeserializeDataFuncImpl(node);
    // 生成get_typeobject函数的实现
    generateGetTypeObjectFuncImpl(node);
    // 生成get_instancehandle函数的实现
    generateGetInstanceHandleFuncImpl(node);
    // 生成has_key函数的实现
    generateHasKeyFuncImpl(node);
    // 生成get_typename函数的实现
    generateGetTypenameFuncImpl(node);
}

void CppLangTypeSupportSourceVisitor::generateGetInstanceFuncImpl(ConstrTypeDclNode& node) {
    std::string structName = typeNameVisitor_->findName(&node);
    content_ += structName + "TypeSupport* " + structName + "TypeSupport::get_instance() {\n";
    content_ += "    static " + structName + "TypeSupport instance;\n";
    content_ += "    return &instance;\n";
    content_ += "}\n\n";
}

void CppLangTypeSupportSourceVisitor::generateCreateDataFuncImpl(ConstrTypeDclNode& node) {
    std::string structName = typeNameVisitor_->findName(&node);
    content_ += "void* " + structName + "TypeSupport::create_data() {\n";
    content_ += "    return new " + structName + "();\n";
    content_ += "}\n\n";
}

void CppLangTypeSupportSourceVisitor::generateDeleteDataFuncImpl(ConstrTypeDclNode& node) {
    std::string structName = typeNameVisitor_->findName(&node);
    content_ += "void " + structName + "TypeSupport::delete_data(void* data) {\n";
    content_ += "    delete static_cast<" + structName + "*>(data);\n";
    content_ += "}\n\n";
}

void CppLangTypeSupportSourceVisitor::generateCopyDataFuncImpl(ConstrTypeDclNode& node) {
    std::string structName = typeNameVisitor_->findName(&node);
    content_ += "int " + structName + "TypeSupport::copy_data(void* dst, void* src) {\n";
    content_ += "    " + structName + "* dstData = static_cast<" + structName + "*>(dst);\n";
    content_ += "    " + structName + "* srcData = static_cast<" + structName + "*>(src);\n";
    content_ += "    *dstData = *srcData;\n";
    content_ += "    return 0;\n";
    content_ += "}\n\n";
}

void CppLangTypeSupportSourceVisitor::generateGetSerializedDataSizeFuncImpl(ConstrTypeDclNode& node) {
    StructDefNode* structNode = dynamic_cast<StructDefNode*>(&node);
    if (structNode) {
        getSerializeSizeVisitor_->visit(*structNode);
    }
    UnionDefNode* unionNode = dynamic_cast<UnionDefNode*>(&node);
    if (unionNode) {
        getSerializeSizeVisitor_->visit(*unionNode);
    }
    content_ += getSerializeSizeVisitor_->getContent();
}

void CppLangTypeSupportSourceVisitor::generateGetMaxSerializedDataSizeFuncImpl(ConstrTypeDclNode& node) {
    StructDefNode* structNode = dynamic_cast<StructDefNode*>(&node);
    if (structNode) {
        getMaxSerializeSizeVisitor_->visit(*structNode);
    }
    UnionDefNode* unionNode = dynamic_cast<UnionDefNode*>(&node);
    if (unionNode) {
        getMaxSerializeSizeVisitor_->visit(*unionNode);
    }
    content_ += getMaxSerializeSizeVisitor_->getContent();
}

void CppLangTypeSupportSourceVisitor::generateSerializeDataFuncImpl(StructDefNode& node) {
    serializeVisitor_->visit(node);
    content_ += serializeVisitor_->getContent();
}

void CppLangTypeSupportSourceVisitor::generateSerializeDataFuncImpl(UnionDefNode& node) {
    serializeVisitor_->visit(node);
    content_ += serializeVisitor_->getContent();
}

void CppLangTypeSupportSourceVisitor::generateDeserializeDataFuncImpl(StructDefNode& node) {
    deserializeVisitor_->visit(node);
    content_ += deserializeVisitor_->getContent();
}

void CppLangTypeSupportSourceVisitor::generateDeserializeDataFuncImpl(UnionDefNode& node) {
    deserializeVisitor_->visit(node);
    content_ += deserializeVisitor_->getContent();
}

void CppLangTypeSupportSourceVisitor::generateGetTypeObjectFuncImpl(ConstrTypeDclNode& node) {
    std::string structName = typeNameVisitor_->findName(&node);
    content_ += "TypeObject* " + structName + "TypeSupport::get_typeobject() {\n";
    content_ += "    return nullptr;\n";
    content_ += "}\n\n";
}

void CppLangTypeSupportSourceVisitor::generateMakeKeyFuncImpl(ConstrTypeDclNode& node) {
    // 序列化key的内部函数
    // struct
    StructDefNode* structNode = dynamic_cast<StructDefNode*>(&node);
    if (structNode) {
        serializeKeyVisitor_->visit(*structNode);
    }
    // union
    UnionDefNode* unionNode = dynamic_cast<UnionDefNode*>(&node);
    if (unionNode) {
        serializeKeyVisitor_->visit(*unionNode);
    }
    content_ += serializeKeyVisitor_->getContent();
    // make_key函数
    std::string structName = typeNameVisitor_->findName(&node);
    content_ += "int " + structName + "TypeSupport::MakeKey(const void* data, InstanceHandle_t& iHandle, bool forceMd5) {\n";
    ++indentLevel_;
    content_ += indent() + "unsigned int serializedSize = get_serialized_data_size((void*)data, 0);\n";
    content_ += indent() + "SerializedBuffer buffer;\n";
    content_ += indent() + "buffer.buffer_size = serializedSize;\n";
    content_ += indent() + "buffer.buffer = new char[buffer.buffer_size];\n";
    content_ += indent() + "AGIDDSCdrSerializer cdr(&buffer);\n";
    content_ += indent() + "ReturnCode_t ret = get_instancehandle((void*)data, &cdr, iHandle, forceMd5);\n";
    content_ += indent() + "delete[] buffer.buffer;\n";
    content_ += indent() + "return ret == RETCODE_OK ? 0 : -1;\n";
    --indentLevel_;
    content_ += "}\n\n";
}

void CppLangTypeSupportSourceVisitor::generateGetInstanceHandleFuncImpl(ConstrTypeDclNode& node) {
    // 序列化key的内部函数
    // struct
    StructDefNode* structNode = dynamic_cast<StructDefNode*>(&node);
    if (structNode) {
        serializeKeyVisitor_->visit(*structNode);
    }
    // union
    UnionDefNode* unionNode = dynamic_cast<UnionDefNode*>(&node);
    if (unionNode) {
        serializeKeyVisitor_->visit(*unionNode);
    }
    content_ += serializeKeyVisitor_->getContent();
    // get_instancehandle函数
    std::string structName = typeNameVisitor_->findName(&node);
    content_ += "ReturnCode_t " + structName + "TypeSupport::get_instancehandle(void* data, AGIDDSCdrSerializer* cdr, InstanceHandle_t& iHandle, bool forceMd5) {\n";
    ++indentLevel_;
    // 判断是否有key
    content_ += indent() + "if (!has_key()) {\n";
    ++indentLevel_;
    content_ += indent() + "iHandle = HANDLE_NIL;\n";
    content_ += indent() + "return RETCODE_OK;\n";
    --indentLevel_;
    content_ += indent() + "}\n";
    // 有key，调用serialize_key函数
    content_ += indent() + "int ret = serialize_key(data, cdr, forceMd5);\n";
    content_ += indent() + "if (ret != 0) {\n";
    ++indentLevel_;
    content_ += indent() + "fprintf(stderr, \"Failed to serialize key.\\n\");\n";
    content_ += indent() + "return RETCODE_ERROR;\n";
    --indentLevel_;
    content_ += indent() + "}\n";
    // 调用cdr的getKeyHash函数
    content_ += indent() + "if (!cdr->getKeyHash((char*)&iHandle, forceMd5)) {\n";
    ++indentLevel_;
    content_ += indent() + "fprintf(stderr, \"Failed to get key hash\\n\");\n";
    content_ += indent() + "return RETCODE_ERROR;\n";
    --indentLevel_;
    content_ += indent() + "}\n";
    content_ += indent() + "return RETCODE_OK;\n";
    --indentLevel_;
    content_ += "}\n\n";
}

void CppLangTypeSupportSourceVisitor::generateHasKeyFuncImpl(StructDefNode& node) {
    std::string structName = typeNameVisitor_->findName(&node);
    content_ += "bool " + structName + "TypeSupport::has_key() {\n";
    bool hasKey = false;
    // 遍历结构体成员
    for (auto& member : node.members_->nodes_) {
        // 判断annotations_中是否有KEY属性
        if (!member->annotations_) {
            continue;
        }
        for (auto& attr : member->annotations_->nodes_) {
            if (attr->annotation_ == MemberAnnotationNode::AnnotationType::KEY_ANNOTATION) {
                hasKey = true;
                break;
            }
        }
    }
    ++indentLevel_;
    if (hasKey) {
        content_ += indent() + "return true;\n";
    } else {
        content_ += indent() + "return false;\n";
    }
    --indentLevel_;
    content_ += "}\n\n";
}

void CppLangTypeSupportSourceVisitor::generateHasKeyFuncImpl(UnionDefNode& node) {
    std::string structName = typeNameVisitor_->findName(&node);
    content_ += "bool " + structName + "TypeSupport::has_key() {\n";
    if (node.switchType_->key_) {
        content_ += "    return true;\n";
    } else {
        content_ += "    return false;\n";
    }
    content_ += "}\n\n";
}

void CppLangTypeSupportSourceVisitor::generateGetTypenameFuncImpl(ConstrTypeDclNode& node) {
    std::string structName = typeNameVisitor_->findName(&node);
    content_ += "const char* " + structName + "TypeSupport::get_typename() {\n";
    content_ += "    return \"" + structName + "\";\n";
    content_ += "}\n\n";
}
